package com.luck.util;

import com.luck.model.pojo.AssignWeight;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * 分配权重工具类
 */
public class AssignWeightUtil {
    public static void main(String[] args) {
        List<AssignWeight> list = new ArrayList<>();
        int index = 2;
        for (int i = 10; i >= 8; i--) {
            AssignWeight assignWeight = new AssignWeight();
            assignWeight.setWeight(i);
            assignWeight.setCount(0);
            assignWeight.setName("优先级"+i);
            assignWeight.setLevel(index--);
            list.add(assignWeight);
        }
        System.out.println(list);
        /*list.sort((o1, o2) -> {
            if (o2.getLevel() == o1.getLevel()) {
                return o2.getWeight() - o1.getWeight();
            }
            return o2.getLevel() - o1.getLevel();
        });*/
        list.sort(Comparator.comparingInt(AssignWeight::getWeight));
        System.out.println(list);
        long l = System.currentTimeMillis();
        assignChoose(list);
        System.out.println("时间间隔:" + (System.currentTimeMillis()-l));
    }
    public static void assignChoose(List<AssignWeight> list){
        for (int i = 0; i < 55; i++) {
            AssignWeight assign = assignRand(list);
            System.out.println("需要新增等级为:" + assign.getWeight());
            int level = assign.getLevel();
            list.get(level).setCount(list.get(level).getCount() + 1);
            for (int j = 0; j < list.size(); j++) {
                System.out.print("weight:"+list.get(j).getWeight()+",count:"+list.get(j).getCount()+"     ");
            }
            System.out.println();
        }
    }
    /**
     * 1
     * 缺点：对于占比另类的不太精确(如: 9:8:7)
     * 优点：不必遍历全部集合值
     * @param list
     * @return
     */
    public static AssignWeight assign(List<AssignWeight> list) {
        list.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
        int size = list.size();
        // 相邻权重比例
        double[] weightD = new double[size - 1];
        // 相邻已分配 比例
        double[] countD = new double[size - 1];
        AssignWeight oneWeight = list.get(0);
        int weightFlag = oneWeight.getWeight();
        int countFlag = oneWeight.getCount();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (countFlag == 0) {
            return list.get(0);
        }
        int index = 0;
        for (int i = 0; i < size - 1; i++) {
            AssignWeight indexAssignWeight = list.get(i + 1);
            int indexWeight = indexAssignWeight.getWeight();
            int indexCount = indexAssignWeight.getCount();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (indexCount == 0) {
                index = i + 1;
                break;
            }
            weightD[i] = (double) weightFlag / indexWeight;
            countD[i] = (double) countFlag / indexCount;
            weightFlag = indexWeight;
            countFlag = indexCount;
            if (weightD[i] == countD[i]) {
                continue;
            }
            index = weightD[i] > countD[i] ? 0 : i + 1;
            break;
        }
        return list.get(index);
    }

    /**
     * 2
     * 缺点：遍历集合全部对象
     * 优点：按照占比分配相对均匀
     * @param list
     * @return
     */
    public static AssignWeight assignUniform(List<AssignWeight> list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        int size = list.size();
        if (size == 1) {
            return list.get(0);
        }
        list.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
        int weightTotal = 0;
        int countTotal = 0;
        int[] weight = new int[size];
        int[] count = new int[size];
        for (int i = 0; i < size; i++) {
            AssignWeight indexAssignWeight = list.get(i);
            weight[i] = indexAssignWeight.getWeight();
            count[i] = indexAssignWeight.getCount();
            weightTotal += weight[i];
            countTotal += count[i];
        }
        // 权重所占比例
        double[] weightD = new double[size];
        // 已分配所占比例
        double[] countD = new double[size];
        int index = 0;
        for (int i = 0; i < size; i++) {
            weightD[i] = (double) weight[i] / weightTotal;
            countD[i] = (double) count[i] / countTotal;
            if (countD[i] >= weightD[i]) {
                continue;
            }
            index = i;
            break;
        }
        return list.get(index);
    }

    /**
     * 3.对第一种方法进行优化
     * @param list
     * @return
     */
    public static AssignWeight assignSpecialty(List<AssignWeight> list) {
        list.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
        int size = list.size();
        // 相邻权重比例
        double[] weightD = new double[size - 1];
        // 相邻已分配 比例
        double[] countD = new double[size - 1];
        AssignWeight oneWeight = list.get(0);
        int weightFlag = oneWeight.getWeight();
        int countFlag = oneWeight.getCount();
        if (countFlag == 0) {
            return list.get(0);
        }
        int index = 0;
        for (int i = 0; i < size - 1; i++) {
            AssignWeight indexAssignWeight = list.get(i + 1);
            int indexWeight = indexAssignWeight.getWeight();
            int indexCount = indexAssignWeight.getCount();
            if (indexCount == 0) {
                index = i + 1;
                break;
            }
            weightD[i] = (double) weightFlag / indexWeight;
            countD[i] = (double) countFlag / indexCount;
            weightFlag = indexWeight;
            countFlag = indexCount;
            if (weightD[i] == countD[i]) {
                index = i;
                continue;
            }
            if (weightD[i] > countD[i]) {
                // 已分配 < 所占权重
                index = i;
                break;
            } else if (i == size - 2){
                // 最小权重占比
                index = i + 1;
                break;
            }
        }
        return list.get(index);
    }

    /**
     * 4.随机分配
     * @param list
     * @return
     */
    public static AssignWeight assignRand(List<AssignWeight> list) {
        int size;
        if (list == null || (size = list.size()) == 0) {
            return null;
        }
        if (size == 1) {
            return list.get(0);
        }
        int totalWeight = 0;
        int[] weightSegment = new int[size];
        for (int i = 0; i < size; i++) {
            AssignWeight indexAssign = list.get(i);
            Integer indexWeight = indexAssign.getWeight();
            totalWeight += indexWeight;
            weightSegment[i] = totalWeight;
            System.out.print(weightSegment[i] + ",");
        }
        System.out.println();
        int rand = (int) (1 + Math.random() * (totalWeight));
        System.out.println("随机数：" + rand);
        int index = 0;
        for (int i = size - 2; i >= 0; i--) {
            if (rand > weightSegment[i]) {
                index = i + 1;
                break;
            }
        }
        return list.get(index);
    }
}
